<?php
declare(strict_types=1);

namespace App\Service;

use App\Constants\StrStatus;
use App\Constants\XZXResponseCode;
use App\Exception\XZXValidationException;
use App\Model\Dao\TradeOrderDetailDao;
use App\Model\Dao\TradeOrderForceSuccessDao;
use App\Model\Dao\TradeOrderForceSuccessSingleDao;
use App\Model\Dao\TradeOrderLogDao;
use App\Model\Enum\CommonReviewStatusEnum;
use App\Model\Enum\OrderHandleStatusEnum;
use App\Model\Enum\OrderReviewStatusEnum;
use App\Model\Enum\OrderSettleStatusEnum;
use App\Model\Enum\OrderTransTypeEnum;
use App\Model\Enum\StatusEnum;
use App\Model\Enum\TradeForceSuccessStatusEnum;
use App\Utils\CustomUtils;
use App\Utils\DateUtils;
use App\Utils\NumberUtils;
use Hyperf\Database\Query\Builder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Arr;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;


class TradeOrderForceSuccessService {

    /**
     * @Inject()
     * @var TradeOrderDetailDao
     */
    private $TradeOrderDetailDao;

    /**
     * @Inject()
     * @var TradeOrderForceSuccessDao
     */
    private $TradeOrderForceSuccessDao;

    /**
     * @Inject()
     * @var TradeOrderForceSuccessSingleDao
     */
    private $TradeOrderForceSuccessSingleDao;

    /**
     * @Inject()
     * @var TradeOrderReviewService
     */
    private $TradeOrderReviewService;

    /**
     * @Inject()
     * @var TradeOrderLogDao
     */
    private $TradeOrderLogDao;


    public function get ($param) {
        $result = $this->TradeOrderForceSuccessDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        (isset($result['createTime']) && !empty($result['createTime'])) && $result['createTime'] = DateUtils::getDateTime($result['createTime']);

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $result);
    }

    /**
     * 批量补单提交
     *
     * @param $params
     *
     * @return array
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     * @throws \Throwable
     */
    public function batchApply ($params) {

        $filepath = $params['filepath'];
        $createBy = $params['createBy'];

        // 解析excel文件
        $reader = IOFactory::createReaderForFile($filepath);
        $reader->setReadDataOnly(true);
        $spreadsheet = $reader->load($filepath);

        $worksheet = $spreadsheet->getActiveSheet();

        $tradeNoList = array_map(function ($row) {
            return reset($row);
        }, $worksheet->toArray());

        // 查询order列表
        $orderDetailList = $this->TradeOrderDetailDao->getWhereList(function (Builder $query) use ($tradeNoList) {
            $query->whereIn('tradeNo', $tradeNoList);
        });

        if (empty($orderDetailList)) {
            throw new \Exception('未找到相关订单信息');
        }

        Db::beginTransaction();

        try {

            $batchId = CustomUtils::createUUID();

            $update = [
                'id'           => $batchId,
                'batch'        => CustomUtils::createBatchNo(),
                'uploadFile'   => $filepath,
                'handleStatus' => OrderHandleStatusEnum::INIT,
                'createTime'   => time(),
                'createBy'     => $createBy,
                'updateBy'     => $createBy,
            ];

            $this->TradeOrderForceSuccessDao->insert($update);

            $applyList = [];

            foreach ($orderDetailList as $orderDetail) {
                array_push($applyList, [
                    'id'           => CustomUtils::createUUID(),
                    'batchId'      => $batchId,
                    'orderId'      => $orderDetail['id'],
                    'tradeNo'      => $orderDetail['tradeNo'],
                    'mchId'        => $orderDetail['mchId'],
                    'mchNo'        => $orderDetail['mchNo'],
                    'transAmount'  => $orderDetail['mchTransAmount'],
                    'transReason'  => '批量补单',
                    'handleStatus' => OrderHandleStatusEnum::INIT,
                    'settleStatus' => OrderSettleStatusEnum::DONE,
                    'createTime'   => time(),
                    'createBy'     => $createBy,
                    'updateBy'     => $createBy,
                ]);
            }

            $this->TradeOrderForceSuccessSingleDao->insert($applyList);

            Db::commit();
        } catch (\Throwable $e) {

            Db::rollBack();
            throw $e;
        }

        return CustomUtils::buildSuccess();
    }

    public function handleBatchReviewFirst ($params) {

        $id        = $params['id'];
        $isApprove = $params['isApprove'];
        $remark    = $params['remark'];
        $createBy  = $params['createBy'];

        $info = $this->TradeOrderForceSuccessDao->get($id);

        if (!$info) {
            throw new \Exception('未找到数据');
        }

        if ($info['reviewStatus'] != 0) {
            throw new \Exception('不处于待审核状态');
        }

        $applyList   = $this->TradeOrderForceSuccessSingleDao->getWhereList(['batchId' => $id]);
        $tradeNoList = array_map(function ($apply) {
            return $apply['tradeNo'];
        }, $applyList);

        $ret = CustomUtils::buildSuccess();

        // 处理对应补单申请
        $re = $this->TradeOrderReviewService->handleForceSuccessReview([
            'isApprove'   => $isApprove,
            'createBy'    => $createBy,
            'remark'      => $remark,
            'reviewLevel' => 1,
            'tradeNoList' => $tradeNoList,
        ]);

        if (CustomUtils::isError($re)) {
            $ret = $re;
        }
        else {
            // 更新申请记录状态
            $this->TradeOrderForceSuccessDao->update($id, [
                'handleStatus' => $isApprove ? OrderHandleStatusEnum::FIRST_APPROVE : OrderHandleStatusEnum::FIRST_REJECT,
                'reviewStatus' => $isApprove ? OrderReviewStatusEnum::APPROVE : OrderReviewStatusEnum::REJECT,
                'reviewBy'     => $createBy,
                'reviewRemark' => $remark,
                'reviewTime'   => time(),
            ]);
        }

        return $ret;
    }

    /**
     * @param $params
     *
     * @return array
     * @throws \Throwable
     */
    public function handleBatchReviewSecond ($params) {

        $id        = $params['id'];
        $isApprove = $params['isApprove'];
        $remark    = $params['remark'];
        $createBy  = $params['createBy'];

        $info = $this->TradeOrderForceSuccessDao->get($id);

        if (!$info) {
            throw new \Exception('未找到数据');
        }

        if ($info['reviewStatus'] != OrderReviewStatusEnum::APPROVE) {
            throw new \Exception('初审未通过');
        }

        if ($info['reReviewStatus'] != OrderReviewStatusEnum::INIT) {
            throw new \Exception('不处于待审核状态');
        }

        $applyList   = $this->TradeOrderForceSuccessSingleDao->getWhereList(['batchId' => $id]);
        $tradeNoList = array_map(function ($apply) {
            return $apply['tradeNo'];
        }, $applyList);

        $ret = CustomUtils::buildSuccess();

        // 处理对应补单申请
        $re = $this->TradeOrderReviewService->handleForceSuccessReview([
            'isApprove'   => $isApprove,
            'createBy'    => $createBy,
            'remark'      => $remark,
            'reviewLevel' => 2,
            'tradeNoList' => $tradeNoList,
        ]);

        if (CustomUtils::isError($re)) {
            $ret = $re;
        }
        else {
            // 更新申请记录状态
            $this->TradeOrderForceSuccessDao->update($id, [
                'handleStatus'   => $isApprove ? OrderHandleStatusEnum::SECOND_APPROVE : OrderHandleStatusEnum::SECOND_REJECT,
                'reReviewStatus' => $isApprove ? OrderReviewStatusEnum::APPROVE : OrderReviewStatusEnum::REJECT,
                'reReviewBy'     => $createBy,
                'reReviewRemark' => $remark,
                'reReviewTime'   => time(),
            ]);
        }

        return $ret;
    }

    public function add ($param) {

        $createBy = $param['createBy'];
        $data     = [
            'id'         => CustomUtils::createUUID(),
            'batch'      => date('YmdHis').NumberUtils::random(4),
            'uploadFile' => $param['uploadFile'],
            'createTime' => time(),
            'createBy'   => $param['createBy'],
            'updateBy'   => $param['createBy'],
        ];

        // 下载文件
        $uploadFile = $param['uploadFile'];
        $path       = BASE_PATH.'/runtime/upload/';
        @mkdir($path, 0755, true);
        $filepath = $path.(new \SplFileInfo($uploadFile))->getFileName();
        file_put_contents($filepath, file_get_contents($uploadFile));

        // 读取文件
        $reader = IOFactory::createReaderForFile($filepath);
        $reader->setReadDataOnly(true);
        $spreadsheet = $reader->load($filepath);

        $worksheet = $spreadsheet->getActiveSheet();

        // 获取值
        $tradeNoList = array_map(function ($row) {
            return reset($row);
        }, $worksheet->toArray());

        // 去掉空记录
        $tradeNoList = array_filter($tradeNoList, function ($item) {
            return !!$item;
        });

        // 查询order列表
        $orderDetailList = $this->TradeOrderDetailDao->getWhereList(function (Builder $query) use ($tradeNoList) {
            $query->whereIn('tradeNo', $tradeNoList);
            $query->where('transStatus', 5);
        });
        if (empty($orderDetailList)) {
            throw new \Exception('未找到符合补单条件的订单信息');
        }

        // 检查有无申请中/审核通过的单号
        $processTradeNoList = $this->TradeOrderForceSuccessSingleDao->getWhereList(function (Builder $query) use ($tradeNoList) {
            $query->whereIn('tradeNo', $tradeNoList);
            $query->whereIn('handleStatus', [
                OrderHandleStatusEnum::INIT,
                OrderHandleStatusEnum::FIRST_APPROVE,
                OrderHandleStatusEnum::SECOND_APPROVE,
            ]);
        });

        if (!empty($processTradeNoList)) {
            $processTradeNoList = array_map(function ($item) {
                return $item['tradeNo'];
            }, $processTradeNoList);

            return CustomUtils::buildError('单号已在补单申请', XZXResponseCode::FAILED_CODE, [
                'processTradeNoList' => $processTradeNoList,
            ]);
        }

        Db::beginTransaction();

        try {

            $batchId = $data['id'];
            $this->TradeOrderForceSuccessDao->insert($data);

            $applyList = [];

            foreach ($orderDetailList as $orderDetail) {
                array_push($applyList, [
                    'id'           => CustomUtils::createUUID(),
                    'batchId'      => $batchId,
                    'orderId'      => $orderDetail['id'],
                    'tradeNo'      => $orderDetail['tradeNo'],
                    'mchId'        => $orderDetail['mchId'],
                    'mchNo'        => $orderDetail['mchNo'],
                    'transAmount'  => $orderDetail['mchTransAmount'],
                    'transReason'  => '批量补单',
                    'handleStatus' => OrderHandleStatusEnum::INIT,
                    'settleStatus' => OrderSettleStatusEnum::DONE,
                    'createTime'   => time(),
                    'createBy'     => $createBy,
                    'updateBy'     => $createBy,
                ]);
            }

            $this->TradeOrderForceSuccessSingleDao->insert($applyList);

            Db::commit();

        } catch (\Throwable $e) {
            Db::rollBack();
            throw $e;
        }

        return CustomUtils::buildSuccess(['id' => $batchId]);
    }

    public function edit ($param) {
        $info = $this->TradeOrderForceSuccessDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $id   = $param['id'];
        $data = [];
        foreach ($param as $k => $v) {
            if ($k == "id") {
                continue;
            }
            if (isset($v)) {
                $data[$k] = $v;
            }
        }

        try {
            $this->TradeOrderForceSuccessDao->update($id, $data);
        } catch (\Throwable $th) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), CustomUtils::xzxEmptyObject());
    }

    public function list (array $param) {

        $limit = $param['limit'];
        $page  = $param['page'];

        $total = $this->TradeOrderForceSuccessDao->getCount($param);
        $list  = $this->TradeOrderForceSuccessDao->getList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $v['strStatus']         = TradeForceSuccessStatusEnum::getLabel($v['status']);
            $v['strHandleStatus']   = OrderHandleStatusEnum::getLabel($v['handleStatus']);
            $v['strReviewStatus']   = CommonReviewStatusEnum::getLabel($v['reviewStatus']);
            $v['strReReviewStatus'] = CommonReviewStatusEnum::getLabel($v['reReviewStatus']);
            $list[$k]               = $v;
        }

        $data = [
            'total' => $total,
            'list'  => $list,
        ];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $data);
    }

    /**
     * 写入交易变更日志
     *
     * @param array $orderList
     */
    public function addOrderLog ($orderList = []) {

        // TODO 补单的交易变更日志

        // $logList = [];
        //
        // foreach ($orderList as $order) {
        //     $log = [
        //         'id'            => CustomUtils::createUUID(),
        //         'transId'       => $order['id'],
        //         'mchId'         => $order['mchId'],
        //         'mchNo'         => $order['mchNo'],
        //         'orderId'       => $order['orderId'],
        //         'tradeNo'       => $order['tradeNo'],
        //         'tradeNewNo'    => $order['tradeNewNo'],
        //         'transType'     => OrderTransTypeEnum::FORCE_SUCCESS,
        //         'transCurrency' => $order['transCurrency'],
        //         'transAmount'   => $order['transAmount'],
        //         'transReason'   => $order['transReason'],
        //         'handleStatus'  => $order['handleStatus'],
        //         'status'        => StatusEnum::ON,
        //         'createTime'    => time(),
        //         'createBy'      => $order['createBy'],
        //     ];
        //
        //     array_push($logList, $log);
        // }
        //
        // $this->TradeOrderLogDao->insert($logList);
    }

}
